#if !defined(LOCKER_H)
#define LOCKER_H

#include <exception>
#include <pthread.h>
#include <semaphore.h>

/// @brief 信号量封装类
class sem
{
private:
    sem_t m_sem;

public:
    /// @brief 创建并初始化信号量
    sem()
    {
        if (sem_init(&m_sem, 0, 0) != 0)
            // 创建失败
            throw std::exception();
    }

    /// @brief 创建并使用值初始化信号量
    /// @param num
    sem(int num)
    {
        if (sem_init(&m_sem, 0, num) != 0)
            // 创建失败
            throw std::exception();
    }

    /// @brief 销毁信号量
    ~sem()
    {
        sem_destroy(&m_sem);
    }

    /// @brief 等待信号量
    /// @return 是否成功
    bool wait()
    {
        return sem_wait(&m_sem) == 0;
    }

    /// @brief 增加信号量
    /// @return 是否成功
    bool post()
    {
        return sem_post(&m_sem) == 0;
    }
};

/// @brief 互斥锁封装类
class locker
{
private:
    pthread_mutex_t m_mutex;

public:
    /// @brief 创建并初始化互斥锁
    locker()
    {
        if (pthread_mutex_init(&m_mutex, NULL) != 0)
            throw std::exception();
    }

    /// @brief 销毁互斥锁
    ~locker()
    {
        pthread_mutex_destroy(&m_mutex);
    }

    /// @brief 获取互斥锁
    /// @return 是否成功
    bool lock()
    {
        return pthread_mutex_lock(&m_mutex) == 0;
    }

    /// @brief 释放互斥锁
    /// @return 是否成功
    bool unlock()
    {
        return pthread_mutex_unlock(&m_mutex) == 0;
    }

    /// @brief 获取锁
    /// @return
    pthread_mutex_t *getMutex()
    {
        return &m_mutex;
    }
};

class cond
{
private:
    // pthread_mutex_t m_mutex;
    pthread_cond_t m_cond;

public:
    /// @brief 创建并初始化条件变量
    cond()
    {
        // if (pthread_mutex_init(&m_mutex, NULL) != 0)
            // throw std::exception();
        if (pthread_cond_init(&m_cond, NULL) != 0)
        {
            // pthread_mutex_destroy(&m_mutex);
            throw std::exception();
        }
    }

    /// @brief 销毁条件变量
    ~cond()
    {
        // pthread_mutex_destroy(&m_mutex);
        pthread_cond_destroy(&m_cond);
    }

    /// @brief 等待条件变量
    /// @return 是否成功
    bool wait(pthread_mutex_t *m_mutex)
    {
        int ret = 0;
        // pthread_mutex_lock(&m_mutex);
        ret = pthread_cond_wait(&m_cond, m_mutex);
        // pthread_mutex_unlock(&m_mutex);
        return ret == 0;
    }

    bool timedwait(pthread_mutex_t *m_mutex, struct timespec t)
    {
        int ret = 0;
        // pthread_mutex_lock(&m_mutex);
        ret = pthread_cond_timedwait(&m_cond, m_mutex, &t);
        // pthread_mutex_unlock(&m_mutex);
        return ret == 0;
    }

    /// @brief 唤醒等待条件变量的线程
    /// @return 是否成功
    bool signal()
    {
        return pthread_cond_signal(&m_cond) == 0;
    }

    /// @brief 全局通知等待线程
    /// @return 是否成功
    bool broadcast()
    {
        return pthread_cond_broadcast(&m_cond) == 0;
    }
};

#endif // LOCKER_H
